package org.jerrymouse.jsa4j.search.lucene;

import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.PhraseQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopScoreDocCollector;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.LockObtainFailedException;
import org.jerrymouse.jsa4j.search.Searcher;

public class LuceneSearcher implements Searcher {
	private Analyzer analyzer;
	private Directory directory;

	@Override
	public void makeIndex(String index, String content) {
		IndexWriter indexWriter = null;
		try {
			try {
				indexWriter = new IndexWriter(directory, analyzer, true,
						IndexWriter.MaxFieldLength.LIMITED);
				Document document = new Document();

				document.add(new Field("index", index, Field.Store.YES,
						Field.Index.NOT_ANALYZED));
				document.add(new Field("contents", new StringReader(content),
						Field.TermVector.NO));
				indexWriter.addDocument(document);
				indexWriter.optimize();
			} finally {
				indexWriter.close();
			}
		} catch (CorruptIndexException e) {
			e.printStackTrace();
		} catch (LockObtainFailedException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	@Override
	public List<String> search(String keyword, Integer max) {
		Term term = new Term("contents", keyword);
		TermQuery luceneQuery = new TermQuery(term);
		return search(luceneQuery, max);
	}

	private List<String> search(Query query, Integer max) {
		List<String> result = new ArrayList<String>();
		if (max == null)
			max = 20;
		try {
			IndexSearcher searcher = new IndexSearcher(directory);
			TopScoreDocCollector collector = TopScoreDocCollector.create(max,
					false);
			searcher.search(query, collector);
			ScoreDoc[] hits = collector.topDocs().scoreDocs;
			for (int i = 0; i < hits.length; i++) {
				Document doc = searcher.doc(hits[i].doc);
				result.add(doc.get("index"));
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		return result;
	}

	public void setAnalyzer(Analyzer analyzer) {
		this.analyzer = analyzer;
	}

	public void setDirectory(Directory directory) {
		this.directory = directory;
	}

	@Override
	public List<String> search(List<String> keywords, Integer max) {
		PhraseQuery query = new PhraseQuery();
		for (String keyword : keywords) {
			Term term = new Term("contents", keyword);
			query.add(term);
		}
		return search(query, max);
	}
}
